/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controladores;

import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import modelo.Causa;
import modelo.Movimiento;
import modelo.PasoProcesal;
import modelo.Persona;
import modelo.Tarea;
import modelo.TiposDeCausa;
import modelo.Tramite;

/**
 * Esta clase representa todas las conexiones con la base de datos
 * @author nahuel
 */
public class Conexiones {

    private Conexiones() {
    }

    public static Conexiones getInstance() {
        return ConexionesHolder.INSTANCE;
    }

    public List<Causa> listarCausas() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Causa> listaCausas = (ArrayList<Causa>) getEntity().createQuery("from Causa").getResultList();
            getEntity().getTransaction().commit();
            return listaCausas;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }

    }

    ArrayList<Movimiento> listarMovimientos() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Movimiento> listaMovimientos = (ArrayList<Movimiento>) getEntity().createQuery("from Movimiento where persona_id IS NULL").getResultList();
            getEntity().getTransaction().commit();
            return listaMovimientos;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    ArrayList<PasoProcesal> listarPasos(Long id) {
        try {
            getEntity().getTransaction().begin();
            ArrayList<PasoProcesal> listaPasos = (ArrayList<PasoProcesal>) getEntity().createQuery("from PasoProcesal where causa_id = ?1").setParameter(1, id).getResultList();
            getEntity().getTransaction().commit();
            return listaPasos;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    ArrayList<Tramite> listarTramites2(Long id) {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Tramite> listaTramites = (ArrayList<Tramite>) getEntity().createQuery("from Tramite where ").getResultList();
            getEntity().getTransaction().commit();
            return listaTramites;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    List<Causa> buscarCausas(String numero, String tipo, String juzgado, String descripcion, String caratula, Date inicio, Date cierre) {
        try {
            String consulta = "";
            if (inicio != null) {
                consulta += " and fechaInicio = '" + inicio.toString() + "'";
            }
            if (cierre != null) {
                consulta += " and fechaCierre = '" + cierre.toString() + "'";
            }

            getEntity().getTransaction().begin();
            ArrayList<Causa> listaCausas = (ArrayList<Causa>) getEntity().createQuery(" from Causa where numero LIKE ?1 and tipo LIKE ?2 and juzgado LIKE ?3 and descripcion LIKE ?4 and caratula LIKE ?5" + consulta).setParameter(1, "%" + numero + "%").setParameter(2, "%" + tipo + "%").setParameter(3, "%" + juzgado + "%").setParameter(4, "%" + descripcion + "%").setParameter(5, "%" + caratula + "%").getResultList();
            getEntity().getTransaction().commit();
            return listaCausas;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }
    
    Causa buscarCausa(String numero) {
        try {

            getEntity().getTransaction().begin();
            Causa causa = (Causa) getEntity().createQuery("from Causa where numero = ?1 ").setParameter(1, numero ).getSingleResult();
            getEntity().getTransaction().commit();
            return causa;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    public ArrayList<PasoProcesal> buscarPasoAgenda(String descripcion, Date fecha) {
        try {
            String consulta = "";
            if (fecha != null) {
                consulta += " and fechaVencimiento = '" + fecha.toString() + "'";
            }
            getEntity().getTransaction().begin();
            ArrayList<PasoProcesal> listaPasosProcesales = (ArrayList<PasoProcesal>) getEntity().createQuery("from PasoProcesal where descripcion LIKE ?1"+ consulta + " order by fechaRealizacion" )
                    .setParameter(1, "%" + descripcion + "%")
                    .getResultList();
            getEntity().getTransaction().commit();
            return listaPasosProcesales;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    ArrayList<TiposDeCausa> obtenerTipos() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<TiposDeCausa> tiposCausa = (ArrayList<TiposDeCausa>) getEntity().createQuery("from TiposDeCausa").getResultList();
            getEntity().getTransaction().commit();
            return tiposCausa;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    List<Movimiento> buscarMovimientosCaja(Date fecha, String debe, String haber, String descripcion) {
        try {
            String consulta = "";
            if (!descripcion.equals("")) {
                consulta += " and descripcion LIKE '%" + descripcion + "%'";
            }
            if (!debe.equals("")) {
                consulta += " and debe = " + debe;
            }
            if (!haber.equals("")) {
                consulta += " and haber = " + haber;
            }
            if (fecha != null) {
                consulta += " and fecha = '" + fecha.toString() + "'";
            }
            getEntity().getTransaction().begin();
            ArrayList<Movimiento> listaMovimientos = (ArrayList<Movimiento>) getEntity().createQuery("from Movimiento where persona_id IS NULL" + consulta).getResultList();
            getEntity().getTransaction().commit();
            return listaMovimientos;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    String[] getTotalesMovimientosCaja(Date fecha, String debe, String haber, String descripcion) {
        try {
            String consulta = "";
            if (!descripcion.equals("")) {
                consulta += " and descripcion LIKE '%" + descripcion + "%'";
            }
            if (!debe.equals("")) {
                consulta += " and debe = " + debe;
            }
            if (!haber.equals("")) {
                consulta += " and haber = " + haber;
            }
            if (fecha != null) {
                consulta += " and fecha = '" + fecha.toString() + "'";
            }
            getEntity().getTransaction().begin();
            Object[] objeto = (Object[]) getEntity().createQuery("select COALESCE(SUM(debe),0), COALESCE(SUM(haber),0), COALESCE(SUM(haber - debe),0) from Movimiento where persona_id is NULL" + consulta).getSingleResult();
            getEntity().getTransaction().commit();
            String[] totales = new String[3];
            totales[0] = objeto[0].toString();
            totales[1] = objeto[1].toString();
            totales[2] = objeto[2].toString();
            return totales;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    public Persona getPersona(String numeroDocumento) {
        try {
            getEntity().getTransaction().begin();
            Persona persona = (Persona) getEntity().createQuery("from Persona where numeroDocumento LIKE ?1").setParameter(1, "%" + numeroDocumento + "%").getSingleResult();
            getEntity().getTransaction().commit();
            return persona;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    private static class ConexionesHolder {

        private static final Conexiones INSTANCE = new Conexiones();
        private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("EstudioPU");
        private static final EntityManager em = emf.createEntityManager();
    }

    public EntityManager getEntity() {
        return ConexionesHolder.em;
    }

    public void cerrarEntity() {
        ConexionesHolder.em.close();
    }

    /**
     * Este metodo permite obtener una lista de todos las personas que se
     * encuentran en la base de datos
     * @return Lista de Personas
     */
    public ArrayList<Persona> listarPersonas() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Persona> listaPersonas = (ArrayList<Persona>) getEntity().createQuery("from Persona where activo = 1").getResultList();
            getEntity().getTransaction().commit();
            return listaPersonas;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo permite obtener una lista de todos los abogados que se
     * encuentran en la base de datos
     * @return Lista de Personas
     */
    public ArrayList<Persona> listarAbogados() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Persona> listaAbogados = (ArrayList<Persona>) getEntity().createQuery("from Persona where activo = 1 and numeroMatricula is not NULL").getResultList();
            getEntity().getTransaction().commit();
            return listaAbogados;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo permite obtener una lista de todos las personas que se
     * encuentran en la base de datos que coinciden con los criterios de
     * búsqueda ingresados
     * @return Lista de Personas
     */
    public ArrayList<Persona> buscarPersonas(String tipoDocumento, String documento, String nombre, String direccion, String telefono, String email) {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Persona> listaPersonas = (ArrayList<Persona>) getEntity().createQuery("from Persona where activo = 1 and tipoDocumento LIKE ?1 and numeroDocumento LIKE ?2 and nombre LIKE ?3 and direccion LIKE ?4 and telefono LIKE ?5 and email LIKE ?6").setParameter(1, "%" + tipoDocumento + "%").setParameter(2, "%" + documento + "%").setParameter(3, "%" + nombre + "%").setParameter(4, "%" + direccion + "%").setParameter(5, "%" + telefono + "%").setParameter(6, "%" + email + "%").getResultList();
            getEntity().getTransaction().commit();
            return listaPersonas;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }


    }

    /**
     * Este metodo permite obtener una lista de todos los Abogados (matriculados) que se
     * encuentran en la base de datos que coinciden con los criterios de
     * búsqueda ingresados
     * @return Lista de Personas
     */
    public ArrayList<Persona> buscarAbogados(String tipoDocumento, String documento, String nombre, String direccion, String telefono, String email) {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Persona> listaAbogados = (ArrayList<Persona>) getEntity().createQuery("from Persona where activo = 1 and numeroMatricula is not NULL and tipoDocumento LIKE ?1 and numeroDocumento LIKE ?2 and nombre LIKE ?3 and direccion LIKE ?4 and telefono LIKE ?5 and email LIKE ?6 order by nombre").setParameter(1, "%" + tipoDocumento + "%").setParameter(2, "%" + documento + "%").setParameter(3, "%" + nombre + "%").setParameter(4, "%" + direccion + "%").setParameter(5, "%" + telefono + "%").setParameter(6, "%" + email + "%").getResultList();
            getEntity().getTransaction().commit();
            return listaAbogados;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }

    }

    /**
     * Este metodo obtiene todos los tramites existentes en el sistema
     * @return 
     */
    public ArrayList<Tramite> listarTramites() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Tramite> listaTramites = (ArrayList<Tramite>) getEntity().createQuery("from Tramite order by fechaInicio").getResultList();
            getEntity().getTransaction().commit();
            return listaTramites;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo obtiene todas las tareas existentes en el sistema
     * @return 
     */
    public ArrayList<Tarea> listarTareas() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Tarea> listaTareas = (ArrayList<Tarea>) getEntity().createQuery("from Tarea where (datediff(fecha,now()))>=0 order by fecha").getResultList();
            getEntity().getTransaction().commit();
            return listaTareas;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo obtiene todas las tareas existentes en el sistema
     * @return 
     */
    public ArrayList<PasoProcesal> listarPasosProcesales() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<PasoProcesal> listaPasosProcesales = (ArrayList<PasoProcesal>) getEntity().createQuery("from PasoProcesal where (datediff(fechaVencimiento,now())>=0) order by fechaVencimiento").getResultList();
            getEntity().getTransaction().commit();
            return listaPasosProcesales;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo obtiene todas las tareas existentes en el sistema
     * si la fecha es 4 dias mayor qur la fecha actual
     * @return 
     */
    public ArrayList<Tarea> listarProximasTareas() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Tarea> listaProximasTareas = (ArrayList<Tarea>) getEntity().createQuery("from Tarea where (datediff(fecha,now()))<=4 and (datediff(fecha,now()))>=0 order by fecha").getResultList();
            getEntity().getTransaction().commit();
            return listaProximasTareas;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo obtiene todos los pasos existentes en el sistema
     * si la fecha de vencimeinto es 4 dias mayor qur la fecha actual
     * @return 
     */
    public ArrayList<PasoProcesal> listarProximosPasos() {
        try {
            getEntity().getTransaction().begin();
            ArrayList<PasoProcesal> listaProximosPasos = (ArrayList<PasoProcesal>) getEntity().createQuery("from PasoProcesal where (datediff(fechaVencimiento,now())<=4) and (datediff(fechaVencimiento,now())>=0) order by fechaVencimiento").getResultList();
            getEntity().getTransaction().commit();
            return listaProximosPasos;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo permite guardar un objeto en la base de datos
     * @param object 
     */
    public void persist(Object object) {
        try {
            getEntity().getTransaction().begin();
            getEntity().persist(object);
            getEntity().getTransaction().commit();
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
        }
    }

    public void refresh(Object object) {
        try {
            getEntity().getTransaction().begin();
            getEntity().refresh(object);
            getEntity().getTransaction().commit();
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
        }
    }

    /**
     * Este metodo permite guardar un objeto en la base de datos
     * @param object
     * @return 
     */
    public boolean remove(Object object) {
        try {
            getEntity().getTransaction().begin();
            getEntity().remove(object);
            getEntity().getTransaction().commit();
            return true;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return false;
        }
    }

    public ArrayList<Tramite> buscarTramite(String numero, String descripcion) {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Tramite> listaTramites = (ArrayList<Tramite>) getEntity().createQuery("from Tramite where numero LIKE ?1 and descripcion LIKE ?2").setParameter(1, numero + "%").setParameter(2, descripcion + "%").getResultList();
            getEntity().getTransaction().commit();
            return listaTramites;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    public ArrayList<Tarea> buscarTarea(String descripcion, String lugar, String hora, String numero, Date fecha) {
        try {
            String consulta = "";
            if (fecha != null) {
                consulta += " and fecha = '" + fecha.toString() + "'";
            }
            getEntity().getTransaction().begin();
            ArrayList<Tarea> listaTareas = (ArrayList<Tarea>) getEntity().createQuery("from Tarea where descripcion LIKE ?1 and lugar LIKE ?2 and hora LIKE ?3 and numero LIKE ?4" + consulta + " order by fecha")
                    .setParameter(1, descripcion + "%")
                    .setParameter(2, lugar + "%")
                    .setParameter(3, hora + "%")
                    .setParameter(4, numero + "%")
                    .getResultList();
            getEntity().getTransaction().commit();
            return listaTareas;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo obtiene todos los tramites existentes en el sistema que tienen
     * como cliente a la persona cuyo id se le pasa como parámetro
     * @return 
     */
    public ArrayList<Tramite> listarTramites(Long id) {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Tramite> listaTramites = (ArrayList<Tramite>) getEntity().createQuery("from Tramite where cliente_id = ?1 or apoderado_id = ?1").setParameter(1, id).getResultList();
            getEntity().getTransaction().commit();
            return listaTramites;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }

    /**
     * Este metodo obtiene todas las causas existentes en el sistema que tienen
     * como cliente a la persona cuyo id se le pasa como parámetro
     * @return 
     */
    public ArrayList<Causa> listarCausas(Long id) {
        try {
            getEntity().getTransaction().begin();
            ArrayList<Causa> listaCausas = (ArrayList<Causa>) getEntity().createQuery("from Causa where cliente_id = ?1 or contraparte_id = ?1 or abogadoApoderado_id = ?1 or abogadoContraparte_id = ?1").setParameter(1, id).getResultList();
            getEntity().getTransaction().commit();
            return listaCausas;
        } catch (Exception e) {
            getEntity().getTransaction().rollback();
            return null;
        }
    }
}
